package pixeleditor.ctrl.impl;

import java.awt.Color;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Locale;
import java.util.ResourceBundle;

import javax.swing.AbstractAction;
import javax.swing.JFileChooser;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileNameExtensionFilter;

import pixeleditor.core.Board;
import pixeleditor.gui.Menu;

import common.core.GameMap;
import common.core.Scenery;
import common.core.Tile;
import common.ctrl.IObserver;
import common.gui.IViewable;
import common.gui.impl.HelpDialog;
import common.i18n.ChangeLanguage;
import common.i18n.Language;
import common.util.MapFactory;
import common.util.MyClassLoader;

@SuppressWarnings("serial")
public class MenuCtrl extends AbstractAction implements IObserver {

	private IViewable iv;

	/**
	 * Handles different button events made by the user.
	 */
	@Override
	public void actionPerformed(ActionEvent e) {
		JMenuItem mnuFileNewMap = (JMenuItem) this.getValue("Menu.inewMap");
		JMenuItem mnuFileLoadMap = (JMenuItem) this.getValue("Menu.iloadMap");
		JMenuItem mnuFileSaveMap = (JMenuItem) this.getValue("Menu.isaveMap");
		JMenuItem[] mnuFileLanguageLanguages = new JMenuItem[Menu.NUMBER_OF_LANGUAGES];
		for(int i=0; i<Menu.NUMBER_OF_LANGUAGES; i++) {
			mnuFileLanguageLanguages[i] = (JMenuItem) this.getValue("Menu.ilanguage" + (i+1));
		}

		JMenuItem mnuFileExit = (JMenuItem) this.getValue("Menu.iexit");
		JMenuItem mnuHelpAbout = (JMenuItem) this.getValue("Menu.iabout");
		JMenuItem mnuHelpHelp = (JMenuItem) this.getValue("Menu.ihelp");

		if(e.getSource() == mnuFileExit) {
			System.exit(0);
		}
		else if(e.getSource() == mnuFileNewMap)
			newMap();

		else if(e.getSource() == mnuFileLoadMap) {
			loadMap();
		}
		else if(e.getSource() == mnuFileSaveMap) {
			System.out.println("hejsan");
			saveMap();
		}
		else if(e.getSource() == mnuHelpAbout) {
			JOptionPane.showMessageDialog(null, "Lite om oss");
		}
		else if(e.getSource() == mnuHelpHelp) {
			new HelpDialog();
		}
		else {
			for(int i=0; i<Menu.NUMBER_OF_LANGUAGES; i++) {
				if(e.getSource() == mnuFileLanguageLanguages[i]) {
					ChangeLanguage.setLanguage(ResourceBundle.getBundle(
							ChangeLanguage.LOCALIZE_BUNDLE + "_" + Language.langISO.get(i), Locale.getDefault(), MyClassLoader.getInstance()));
				}
			}
		}

	}
	
	private void newMap() {
		int i = JOptionPane.showConfirmDialog(null, "Vill du spara!?");
		if(i == JOptionPane.YES_OPTION)
			saveMap();

		//Reset all values saved by Board
		Board.getInstance().setScenery(new Scenery(new Tile[60][100]));
		Board.getInstance().setBak(null);
		Board.getInstance().setPlayer1(null);
		Board.getInstance().setPlayer2(null);
		iv.updateView(null);

	}
	
	private void loadMap() {
		String f = File.separator;
		JFileChooser c = new JFileChooser("." + f + "resource" + f + "maps" + f + "xml");
		FileNameExtensionFilter filter = new FileNameExtensionFilter(
	        ".xml", "xml");
	    c.setFileFilter(filter);
	    int r = c.showOpenDialog(null);
	    
	    if(r == JFileChooser.APPROVE_OPTION) {
	    	GameMap gm = MapFactory.getGameMap(c.getSelectedFile().getName());
			Board.getInstance().setScenery(gm.getMap());
			Point p1 = new Point(gm.getPlayersPoint().get(0).x/10, gm.getPlayersPoint().get(0).y/10);
			Point p2 = new Point(gm.getPlayersPoint().get(1).x/10, gm.getPlayersPoint().get(0).y/10);
			Board.getInstance().setPlayer1(p1);
			Board.getInstance().setPlayer2(p2);
			
			if(gm.getBackground().getBackground() != null) 
				Board.getInstance().setBak(gm.getBackground());

			iv.updateView(null);
	    }
	}
	private void saveMap() {
		if(Board.getInstance().getPlayer1() == null || Board.getInstance().getPlayer2() == null) {
			JOptionPane.showMessageDialog(null,  "Please set the players positions and save again!", "Alert", JOptionPane.ERROR_MESSAGE); 
			return;
		}
		String fileName = JOptionPane.showInputDialog("Please enter a file name.");
		if(fileName == null || fileName.equals("")) {
			JOptionPane.showMessageDialog(null,  "You have to type in an file name!", "Alert", JOptionPane.ERROR_MESSAGE); 
			return;
		}
		BufferedWriter writer = null;

		try {
			Tile[][] g = Board.getInstance().getScenery().getTiles();
			/*All this is used to write to an xml file, but no checks are made
			  that checks if it fits with the xsd.
			*/
			writer = new BufferedWriter(new FileWriter("./resource/maps/xml/" + fileName + ".xml"));
			writer.write("<?xml version=\"1.0\"?>");
			writer.newLine();
			writer.write("<Map>");
			writer.newLine();
			writer.write("\t<GameMode>" + Board.getInstance().getMode() + "</GameMode>");
			writer.newLine();
			if(Board.getInstance().getBak() != null) {
				writer.write("\t<BackgroundImage>" + Board.getInstance().getBak().getName() + "</BackgroundImage>");
				writer.newLine();
			}
			else {
				writer.write("\t<BackgroundImage>bak.png</BackgroundImage>");
				writer.newLine();
			}

			addPlayer(Board.getInstance().getPlayer1(), writer);
			addPlayer(Board.getInstance().getPlayer2(), writer);

			//Count how many background and/or tile spaces that is currently in an row
			int background = 0, tiles = 0;
			//Remember the color that the tile before had and the color that the next tile will have
			// same with destructible
			Color l = null, c = null;
			boolean lb = false, cb = false;
			//60 rows
			for(int i=0; i<60; i++) {
				if(g[i][0] != null) {
					l = g[i][0].getColor();
					lb = g[i][0].isDestructible();
				}
				writer.write("\t<Row>");
				writer.newLine();
				//100 columns
				for(int j=0; j<100; j++) {
					//If there is no tile, add one tile of background
					if(g[i][j] == null) {
						background++;
						if(tiles != 0) {
							writeTile(tiles, lb, l.getRed(), l.getGreen(), l.getBlue(), writer);
							tiles = 0;
						}
					}
					//If there is a tile
					else {
						c = g[i][j].getColor();
						cb = g[i][j].isDestructible();
						//Write background if the last space was a background
						if(background != 0) {
							writeBackground(background, writer);
							background = 0;
						}
						if(j > 0 && g[i][j-1] != null) {
							if(c == l && cb == lb) 
								tiles++;
							else if(c != l || cb != lb) {
								writeTile(tiles, lb, l.getRed(), l.getGreen(), l.getBlue(), writer);
								tiles = 1;
							}
						}
						else
							tiles++;

						l = c;
						lb = cb;


					}
				}
				if(background != 0) {
					writeBackground(background, writer);
					background = 0;
				}
				else if(tiles != 0) {
					writeTile(tiles, cb, c.getRed(), c.getGreen(), c.getBlue(), writer);
					tiles = 0;
				}
				writer.write("\t</Row>");
				writer.newLine();

			}
			writer.write("</Map>");
			writer.newLine();
		}
		catch(Exception e) {
			System.out.println(e.getMessage());
		}
		finally {
			try {
				writer.flush();
				writer.close();
			}
			catch (IOException ex) {
				ex.printStackTrace();
			}
		}
	}

	private void writeTile(int tiles, boolean destructible, int red, int green, int blue, BufferedWriter w) {
		String des = destructible ? "true" : "false";
		try {
			w.write("\t\t<Tile destructible=\"" + des + "\" " +
					"red=\"" + red + "\" " +
					"green=\"" + green + "\" " +
					"blue=\"" + blue + "\">" + tiles + "</Tile>");
			w.newLine();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void writeBackground(int tiles, BufferedWriter w) {
		try {
			w.write("\t\t<Background>" + tiles + "</Background>");
			w.newLine();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	private void addPlayer(Point p, BufferedWriter w) {
		try {
			w.write("\t<Player PosX=\"" + p.x + "\" PosY=\"" + p.y + "\"/>");
			w.newLine();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void addView(IViewable iv) {
		this.iv = iv;
	}

}
